home *** CD-ROM | disk | FTP | other *** search
- /*
- HEADER: ;
- TITLE: Frankenstein Cross Assemblers;
- VERSION: 2.0;
- DESCRIPTION: " Reconfigurable Cross-assembler producing Intel (TM)
- Hex format object records. ";
- SYSTEM: UNIX, MS-Dos ;
- FILENAME: fraosub.c;
- WARNINGS: "This software is in the public domain.
- Any prior copyright claims are relinquished.
-
- This software is distributed with no warranty whatever.
- The author takes no responsibility for the consequences
- of its use." ;
- SEE-ALSO: frasmain.c;
- AUTHORS: Mark Zenier;
- */
-
- /*
- description output pass utility routines
- history September 27, 1987
- March 15, 1988 release 1.1 WIDTH
- September 14, 1990 Dosify, 6 char unique names
- */
-
-
- #include <stdio.h>
- #include "frasmdat.h"
- #include "fragcon.h"
-
- #define OUTRESULTLEN 256
- #define NUMHEXPERL 16
- #define SOURCEOFFSET 24
- #define NUMHEXSOURCE 6
-
- int linenumber = 0;
- char lineLbuff[INBUFFSZ];
- int lineLflag = FALSE;
-
- static unsigned char outresult[OUTRESULTLEN];
- static int nextresult;
- static long genlocctr, resultloc;
-
- static char *oeptr;
-
- #define MAXIMPWID 24
-
- static long widthmask[MAXIMPWID+1] =
- {
- /* 0 */ 1L,
- /* 1 */ 1L,
- /* 2 */ (1L << 2 ) -1,
- /* 3 */ (1L << 3 ) -1,
- /* 4 */ (1L << 4 ) -1,
- /* 5 */ (1L << 5 ) -1,
- /* 6 */ (1L << 6 ) -1,
- /* 7 */ (1L << 7 ) -1,
- /* 8 */ (1L << 8 ) -1,
- /* 9 */ (1L << 9 ) -1,
- /* 10 */ (1L << 10 ) -1,
- /* 11 */ (1L << 11 ) -1,
- /* 12 */ (1L << 12 ) -1,
- /* 13 */ (1L << 13 ) -1,
- /* 14 */ (1L << 14 ) -1,
- /* 15 */ (1L << 15 ) -1,
- /* 16 */ (1L << 16 ) -1,
- /* 17 */ (1L << 17 ) -1,
- /* 18 */ (1L << 18 ) -1,
- /* 19 */ (1L << 19 ) -1,
- /* 20 */ (1L << 20 ) -1,
- /* 21 */ (1L << 21 ) -1,
- /* 22 */ (1L << 22 ) -1,
- /* 23 */ (1L << 23 ) -1,
- /* 24 */ (1L << 24 ) -1
- };
-
-
- static long dgethex()
- /*
- description convert the character string pointed to by
- the output expression pointer to a long integer
- globals oeptr, the output expression pointer
- return the value
- */
- {
- long rv = 0;
-
- while( *oeptr != '\0')
- {
- switch(*oeptr)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- rv = (rv << 4) + ((*oeptr) - '0');
- break;
-
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- rv = (rv << 4) + ((*oeptr) - 'a' + 10);
- break;
-
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- rv = (rv << 4) + ((*oeptr) - 'A' + 10);
- break;
-
- default:
- return rv;
- }
-
- oeptr++;
- }
-
- return rv;
- }
-
-
- outphase()
- /*
- description process all the lines in the intermediate file
- globals the input line
- the output expression pointer
- line number
- file name
- the binary output array and counts
- */
- {
- int firstchar;
-
- for(;;)
- {
- if((firstchar = fgetc(intermedf)) == EOF)
- break;
-
- if(firstchar == 'L')
- {
- if(listflag)
- flushlisthex();
-
- if( fgets(&lineLbuff[1], INBUFFSZ-1, intermedf)
- == (char *)NULL)
- {
- frp2error( "error or premature end of intermediate file");
- break;
- }
-
- lineLflag = TRUE;
- }
- else
- {
- finbuff[0] = firstchar;
- if(fgets( &finbuff[1], INBUFFSZ-1, intermedf)
- == (char *)NULL)
- {
- frp2error("error or premature end of intermediate file");
- break;
- }
- }
-
- switch(firstchar)
- {
- case 'E': /* error */
- if(listflag)
- {
- flushsourceline();
- fputs(&finbuff[2], loutf);
- }
- else
- {
- fprintf(loutf, "%s - line %d - %s",
- currentfnm, linenumber, &finbuff[2]);
- }
- break;
-
- case 'L': /* listing */
- linenumber++;
- break;
-
- case 'C': /* comment / uncounted listing */
- if(listflag)
- {
- char *stuff = strchr(finbuff, '\n');
-
- if(stuff != NULL)
- *stuff = '\0';
-
- fprintf(loutf,"%-*.*s",
- SOURCEOFFSET, SOURCEOFFSET, &finbuff[2]);
- if(lineLflag)
- {
- fputs(&lineLbuff[2], loutf);
- lineLflag = FALSE;
- }
- else
- {
- fputc('\n', loutf);
- }
- }
- break;
-
- case 'P': /* location set */
- oeptr = &finbuff[2];
- currseg = dgethex();
- oeptr++;
- genlocctr = locctr = dgethex();
- break;
-
- case 'D': /* data */
- oeptr = &finbuff[2];
- nextresult = 0;
- resultloc = genlocctr;
- outeval();
- if(hexflag)
- outhexblock();
- if(listflag)
- listhex();
- break;
-
- case 'F': /* file start */
- {
- char *tp;
- if( (tp = strchr(finbuff,'\n')) != (char *)NULL)
- *tp = '\0';
- strncpy(currentfnm, &finbuff[2], 100);
- currentfnm[99] = '\0';
- }
- lnumstk[currfstk++] = linenumber;
- linenumber = 0;
- break;
-
- case 'X': /* file resume */
- {
- char *tp;
- if( (tp = strchr(finbuff,'\n')) != (char *)NULL)
- *tp = '\0';
- strncpy(currentfnm, &finbuff[2], 100);
- currentfnm[99] = '\0';
- }
- linenumber = lnumstk[--currfstk];
- break;
-
- default:
- frp2error("unknown intermediate file command");
- break;
- }
- }
-
- if(hexflag)
- flushhex();
-
- if(listflag)
- flushlisthex();
- }
-
- outeval()
- /*
- description convert the polish form character string in the
- intermediate file 'D' line to binary values in the
- output result array.
- globals the output expression pointer
- the output result array
- */
- {
- register long etop = 0;
-
- register struct evstkel *estkm1p = &estk[0];
-
- while( *oeptr != '\0')
- {
- switch(*oeptr)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- etop = (etop << 4) + ((*oeptr) - '0');
- break;
-
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- etop = (etop << 4) + ((*oeptr) - 'a' + 10);
- break;
-
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- etop = (etop << 4) + ((*oeptr) - 'A' + 10);
- break;
-
- #include "fraeuni.h"
- #include "fraebin.h"
- case IFC_SYMB:
- {
- struct symel *tsy;
-
- tsy = symbindex[etop];
- if(tsy -> seg <= 0)
- {
- frp2undef(tsy);
- etop = 0;
- }
- else
- {
- if(tsy -> seg == SSG_EQU ||
- tsy -> seg == SSG_SET)
- {
- frp2warn( "forward reference to SET/EQU symbol");
- }
- etop = tsy -> value;
- }
- }
- break;
-
- case IFC_CURRLOC:
- etop = genlocctr;
- break;
-
- case IFC_PROGCTR:
- etop = locctr;
- break;
-
- case IFC_DUP:
- if(estkm1p >= &estk[PESTKDEPTH-1])
- {
- frp2error("expression stack overflow");
- }
- else
- {
- (++estkm1p)->v = etop;
- }
- break;
-
- case IFC_LOAD:
- if(estkm1p >= &estk[PESTKDEPTH-1])
- {
- frp2error("expression stack overflow");
- }
- else
- {
- (++estkm1p)->v = etop;
- }
- etop = 0;
- break;
-
- case IFC_CLR:
- etop = 0;
- break;
-
- case IFC_CLRALL:
- etop = 0;
- estkm1p = &estk[0];
- break;
-
- case IFC_POP:
- etop = (estkm1p--)->v;
- break;
-
- case IFC_TESTERR:
- if(etop)
- {
- frp2error(
- "expression fails validity test");
- }
- break;
-
- case IFC_SWIDTH:
- if( etop > 0 && etop <= MAXIMPWID)
- {
- if( estkm1p->v < -(widthmask[etop-1]+1) ||
- estkm1p->v > widthmask[etop-1] )
- {
- frp2error(
- "expression exceeds available field width");
- }
- etop = ((estkm1p--)->v) & widthmask[etop];
- }
- else
- frp2error("unimplemented width");
- break;
-
- case IFC_WIDTH:
- if( etop > 0 && etop <= MAXIMPWID)
- {
- if( estkm1p->v < -(widthmask[etop-1]+1) ||
- estkm1p->v > widthmask[etop] )
- {
- frp2error(
- "expression exceeds available field width");
- }
- etop = ((estkm1p--)->v) & widthmask[etop];
- }
- else
- frp2error("unimplemented width");
- break;
-
- case IFC_IWIDTH:
- if( etop > 0 && etop <= MAXIMPWID)
- {
- if( estkm1p->v < 0 ||
- estkm1p->v > widthmask[etop] )
- {
- frp2error(
- "expression exceeds available field width");
- }
- etop = ((estkm1p--)->v) & widthmask[etop];
- }
- else
- frp2error("unimplemented width");
- break;
-
- case IFC_EMU8:
- if( etop >= -128 && etop <= 255)
- {
- outresult[nextresult++] = etop & 0xff;
- }
- else
- {
- outresult[nextresult++] = 0;
- frp2error(
- "expression exceeds available field width");
- }
- genlocctr ++;
- etop = 0;
- break;
-
- case IFC_EMS7:
- if(etop >= -128 && etop <= 127)
- {
- outresult[nextresult++] = etop & 0xff;
- }
- else
- {
- outresult[nextresult++] = 0;
- frp2error(
- "expression exceeds available field width");
- }
- genlocctr ++;
- etop = 0;
- break;
-
- case IFC_EM16:
- if(etop >= -32768L && etop <= 65535L)
- {
- outresult[nextresult++] = (etop >> 8) & 0xff;
- outresult[nextresult++] = etop & 0xff;
- }
- else
- {
- outresult[nextresult++] = 0;
- outresult[nextresult++] = 0;
- frp2error(
- "expression exceeds available field width");
- }
- genlocctr += 2;
- etop = 0;
- break;
-
- case IFC_EMBR16:
- if(etop >= -32768L && etop <= 65535L)
- {
- outresult[nextresult++] = etop & 0xff;
- outresult[nextresult++] = (etop >> 8) & 0xff;
- }
- else
- {
- outresult[nextresult++] = 0;
- outresult[nextresult++] = 0;
- frp2error(
- "expression exceeds available field width");
- }
- genlocctr += 2;
- etop = 0;
- break;
-
- default:
- break;
- }
- oeptr++;
- }
- }
-
- static long lhaddr, lhnextaddr;
- static int lhnew, lhnext = 0;
- static unsigned char listbuffhex[NUMHEXPERL];
-
- flushlisthex()
- /*
- description output the residue of the hexidecimal values for
- the previous assembler statement.
- globals the new hex list flag
- */
- {
- listouthex();
- lhnew = TRUE;
- }
-
- listhex()
- /*
- description buffer the output result to block the hexidecimal
- listing on the output file to NUMHEXPERL bytes per
- listing line.
- globals The output result array and count
- the hex line buffer and counts
- */
- {
- register int cht;
- register long inhaddr = resultloc;
-
- if(lhnew)
- {
- lhaddr = lhnextaddr = resultloc;
- lhnew = FALSE;
- }
-
- for(cht = 0; cht < nextresult; cht++)
- {
- if(lhnextaddr != inhaddr
- || lhnext >= (lineLflag ? NUMHEXSOURCE : NUMHEXPERL ) )
- {
- listouthex();
- lhaddr = lhnextaddr = inhaddr;
- }
- listbuffhex[lhnext++] = outresult[cht];
- lhnextaddr ++;
- inhaddr ++;
- }
- }
-
- listouthex()
- /*
- description print a line of hexidecimal on the listing
- globals the hex listing buffer
- */
- {
- register int cn;
- register int tc;
-
- if(lhnext > 0)
- {
- fputc(hexch((int)lhaddr>>12), loutf);
- fputc(hexch((int)lhaddr>>8), loutf);
- fputc(hexch((int)lhaddr>>4), loutf);
- fputc(hexch((int)lhaddr), loutf);
- fputc(' ', loutf);
-
- for(cn = 0; cn < lhnext; cn++)
- {
- fputc(hexch((int)(tc = listbuffhex[cn])>>4), loutf);
- fputc(hexch(tc), loutf);
- fputc(' ', loutf);
- }
-
- if( ! lineLflag)
- fputc('\n', loutf);
- }
-
- if(lineLflag)
- {
- if(lineLbuff[2] != '\n')
- {
- switch(lhnext)
- {
- case 0:
- fputs("\t\t\t",loutf);
- break;
- case 1:
- case 2:
- case 3:
- fputs("\t\t",loutf);
- break;
- case 4:
- case 5:
- case 6:
- fputs("\t",loutf);
- default:
- break;
- }
-
- fputs(&lineLbuff[2], loutf);
- lineLflag = FALSE;
- }
- else
- {
- fputc('\n', loutf);
- }
- }
-
- lhnext = 0;
- }
-
- #define INTELLEN 32
-
- static long nextoutaddr, blockaddr;
- static int hnextsub;
- static char hlinebuff[INTELLEN];
-
-
- outhexblock()
- /*
- description buffer the output result to group adjacent output
- data into longer lines.
- globals the output result array
- the intel hex line buffer
- */
- {
- long inbuffaddr = resultloc;
- static int first = TRUE;
-
- int loopc;
-
- if(first)
- {
- nextoutaddr = blockaddr = resultloc;
- hnextsub = 0;
- first = FALSE;
- }
-
- for(loopc = 0; loopc < nextresult; loopc++)
- {
- if(nextoutaddr != inbuffaddr || hnextsub >= INTELLEN)
- {
- intelout(0, blockaddr, hnextsub, hlinebuff);
- blockaddr = nextoutaddr = inbuffaddr;
- hnextsub = 0;
- }
- hlinebuff[hnextsub++] = outresult[loopc];
- nextoutaddr++;
- inbuffaddr++;
- }
- }
-
- flushhex()
- /*
- description flush the intel hex line buffer at the end of
- the second pass
- globals the intel hex line buffer
- */
- {
- if(hnextsub > 0)
- intelout(0, blockaddr, hnextsub, hlinebuff);
- if(endsymbol != SYMNULL && endsymbol -> seg > 0)
- intelout(1, endsymbol -> value, 0, "");
- else
- intelout(1, 0L, 0, "");
-
- }
-
-
- intelout(type, addr, count, data)
- int type;
- long addr;
- int count;
- char data[];
- /*
- description print a line of intel format hex data to the output
- file
- parameters see manual for record description
- */
- {
- register int temp, checksum;
-
- fputc(':', hexoutf);
- fputc(hexch(count>>4),hexoutf);
- fputc(hexch(count),hexoutf);
- fputc(hexch((int)addr>>12),hexoutf);
- fputc(hexch((int)addr>>8),hexoutf);
- fputc(hexch((int)addr>>4),hexoutf);
- fputc(hexch((int)addr),hexoutf);
- fputc(hexch(type>>4),hexoutf);
- fputc(hexch(type),hexoutf);
-
- checksum = ((addr >> 8) & 0xff) + (addr & 0xff) + (count & 0xff);
- checksum += type & 0xff;
-
- for(temp = 0; temp < count; temp ++)
- {
- checksum += data[temp] & 0xff;
- fputc(hexch(data[temp] >> 4), hexoutf);
- fputc(hexch(data[temp]), hexoutf);
- }
-
- checksum = (-checksum) & 0xff;
- fputc(hexch(checksum>>4), hexoutf);
- fputc(hexch(checksum), hexoutf);
- fputc('\n',hexoutf);
- }
-
-
- frp2undef(symp)
- struct symel * symp;
- /*
- description second pass - print undefined symbol error message on
- the output listing device. If the the listing flag
- is false, the output device is the standard output, and
- the message format is different.
- parameters a pointer to a symbol table element
- globals the count of errors
- */
- {
- if(listflag)
- {
- flushsourceline();
- fprintf(loutf," ERROR - undefined symbol %s\n", symp ->symstr);
- }
- else
- fprintf(loutf, "%s - line %d - ERROR - undefined symbol %s\n",
- currentfnm, linenumber, symp -> symstr);
- errorcnt++;
- }
-
- frp2warn(str)
- char * str;
- /*
- description second pass - print a warning message on the listing
- file, varying the format for console messages.
- parameters the message
- globals the count of warnings
- */
- {
- if(listflag)
- {
- flushsourceline();
- fprintf(loutf, " WARNING - %s\n", str);
- }
- else
- fprintf(loutf, "%s - line %d - WARNING - %s\n",
- currentfnm, linenumber, str);
- warncnt++;
- }
-
-
- frp2error(str)
- char * str;
- /*
- description second pass - print a message on the listing file
- parameters message
- globals count of errors
- */
- {
- if(listflag)
- {
- flushsourceline();
- fprintf(loutf, " ERROR - %s\n", str);
- }
- else
- fprintf(loutf, "%s - line %d - ERROR - %s\n",
- currentfnm, linenumber, str);
- errorcnt++;
- }
-
- flushsourceline()
- /*
- description flush listing line buffer before an error for
- that line is printed
- */
- {
- if(listflag && lineLflag)
- {
- fputs("\t\t\t", loutf);
- fputs(&lineLbuff[2], loutf);
- lineLflag = FALSE;
- }
- }
-